package com.soft.controller;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.soft.entity.Kanban;
import com.soft.entity.KanbanItem;
import com.soft.entity.Schedule;
import com.soft.mapper.KanbanMapper;
import com.soft.mapper.ScheduleMapper;
import com.soft.service.KanbanService;
import com.soft.service.UserService;

/**
 * 日程接口（/api/schedule）：
 * - 创建/更新/删除/状态变更/查询
 * - 与看板联动：可在创建时生成看板卡片，状态更新时同步列
 */
@RestController
@RequestMapping("/api/schedule")
public class ScheduleController {

    @Autowired
    private ScheduleMapper scheduleMapper;
    @Autowired
    private KanbanService kanbanService;
    @Autowired
    private KanbanMapper kanbanMapper;
    @Autowired
    private UserService userService;

    private static final DateTimeFormatter DTF = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");

    /** 创建请求体 */
    public static class CreateScheduleReq {
        public String title;
        public String content;
        public String startTime; // yyyy-MM-dd HH:mm
        public String endTime;   // yyyy-MM-dd HH:mm
        public String location;
        public String priority; // low/medium/high
        public Integer creatorId; // required
        public Integer teamId; // nullable
        public String remindTime; // yyyy-MM-dd HH:mm or null
    // optional: create kanban item together
    public Integer kanbanId; // nullable
    public Integer columnId; // nullable
    }

    /** 创建日程：必填 title、creatorId、startTime、endTime */
    @PostMapping
    public Map<String, Object> create(@RequestBody CreateScheduleReq req) {
    // 1) 基本参数校验：标题、创建人、起止时间为必填
        if (req == null || req.title == null || req.title.trim().isEmpty()) {
            throw new IllegalArgumentException("title is required");
        }
        if (req.creatorId == null) {
            throw new IllegalArgumentException("creatorId is required");
        }
    // 2) 将字符串时间解析为 LocalDateTime，避免直接使用字符串导致比较/排序出错
        LocalDateTime start = req.startTime != null ? LocalDateTime.parse(req.startTime, DTF) : null;
        LocalDateTime end = req.endTime != null ? LocalDateTime.parse(req.endTime, DTF) : null;
        if (start == null || end == null) {
            throw new IllegalArgumentException("startTime/endTime is required");
        }
        if (end.isBefore(start)) {
            throw new IllegalArgumentException("endTime must be after startTime");
        }
    // 3) 组装实体：设置默认状态、默认优先级与基础字段
        Schedule s = new Schedule();
        s.setTitle(req.title);
        s.setContent(req.content);
        s.setStartTime(start);
        s.setEndTime(end);
        s.setLocation(req.location);
        s.setStatus("todo");
        s.setPriority(req.priority != null ? req.priority : "medium");
        s.setCreatorId(req.creatorId);
        s.setTeamId(req.teamId);
    // 4) 可选提醒时间：有值则解析并保存
        if (req.remindTime != null && !req.remindTime.isEmpty()) {
            s.setRemindTime(LocalDateTime.parse(req.remindTime, DTF));
        }
    // 5) 若从看板创建且未显式传 teamId，则根据看板归属自动补全 teamId
        if (s.getTeamId() == null && req.kanbanId != null) {
            Kanban kb = kanbanMapper.selectById(req.kanbanId);
            if (kb != null && kb.getTeamId() != null) {
                s.setTeamId(kb.getTeamId());
            }
        }
    // 6) 持久化保存日程
        scheduleMapper.insert(s);

    // 7) 选择性：同时创建看板卡片，建立 scheduleId <-> kanbanItem 关联
        if (req.kanbanId != null) {
            KanbanItem item = new KanbanItem();
            item.setKanbanId(req.kanbanId);
            item.setScheduleId(s.getScheduleId());
            if (req.columnId != null) {
                item.setColumnId(req.columnId);
            }
            kanbanService.addItem(item);
        }
    // 8) 返回最小必要信息：新建记录的主键ID
        Map<String, Object> resp = new HashMap<>();
        resp.put("id", s.getScheduleId());
        return resp;
    }

    /** 返回值：日程 + 创建人名称（前端便于展示） */
    public static class ScheduleWithCreatorName {
        private Schedule schedule;
        private String creatorName;
        
        public ScheduleWithCreatorName(Schedule schedule, String creatorName) {
            this.schedule = schedule;
            this.creatorName = creatorName;
        }
        
        public Schedule getSchedule() { return schedule; }
        public void setSchedule(Schedule schedule) { this.schedule = schedule; }
        public String getCreatorName() { return creatorName; }
        public void setCreatorName(String creatorName) { this.creatorName = creatorName; }
    }

    /** 按 ID 查询：附带创建人名称 */
    @GetMapping("/{id}")
    public ScheduleWithCreatorName getById(@PathVariable Integer id) {
    // 1) 读取日程，不存在直接返回 null（与当前接口风格一致）
        Schedule schedule = scheduleMapper.selectById(id);
        if (schedule == null) {
            return null;
        }
    // 2) 通过 userId 查询昵称，兜底回退“用户{id}”
        String creatorName = userService.getNicknameByUserId(schedule.getCreatorId());
        if (creatorName == null) {
            creatorName = "用户" + schedule.getCreatorId();
        }
        return new ScheduleWithCreatorName(schedule, creatorName);
    }

    /** 列表查询：支持按 teamId/creatorId 过滤，按开始时间倒序 */
    @GetMapping
    public List<Schedule> list(@RequestParam(required = false) Integer teamId,
                               @RequestParam(required = false) Integer creatorId) {
    // 1) 组装查询条件：支持 teamId/creatorId 过滤
        QueryWrapper<Schedule> qw = new QueryWrapper<>();
        if (teamId != null) { qw.eq("team_id", teamId); }
        if (creatorId != null) { qw.eq("creator_id", creatorId); }
    // 2) 排序：按开始时间倒序，方便前端显示近期事件
        qw.orderByDesc("start_time");
        return scheduleMapper.selectList(qw);
    }

    /** 状态更新请求体 */
    public static class UpdateStatusReq {
        public String status; // todo/doing/done/canceled
    }

    /** 更新状态：并尝试同步看板卡片到对应列 */
    @PostMapping("/{id}/status")
    public Map<String, Object> updateStatus(@PathVariable Integer id, @RequestBody UpdateStatusReq req) {
    // 1) 查询并校验日程存在性
    Schedule s = scheduleMapper.selectById(id);
    if (s == null) throw new IllegalArgumentException("schedule not found");
    // 2) 解析目标状态，默认回退到 todo
    String st = (req != null && req.status != null) ? req.status : "todo";
    // 3) 原子更新状态（以及更新时间，依赖 Mapper SQL）
    scheduleMapper.updateStatus(id, st);
        // 同步移动看板上关联的卡片到对应状态列
        try {
            kanbanService.syncItemColumnWithStatus(id, st);
        } catch (Exception ignore) {
            // 忽略同步异常，避免影响主流程
        }
    // 4) 返回变更后的状态信息
    Map<String, Object> resp = new HashMap<>();
    resp.put("id", id);
    resp.put("status", st);
        return resp;
    }

    /** 日程内容更新请求体（部分字段可选更新） */
    public static class UpdateScheduleReq {
        public String title;
        public String content;
        public String startTime; // yyyy-MM-dd HH:mm
        public String endTime;   // yyyy-MM-dd HH:mm
        public String location;
        public String priority; // low/medium/high
        public Integer teamId; // nullable
        public String remindTime; // yyyy-MM-dd HH:mm or null
    }

    /** 更新日程内容：只覆盖请求体内非空字段 */
    @PostMapping("/{id}/update")
    public Map<String, Object> update(@PathVariable Integer id, @RequestBody UpdateScheduleReq req) {
    // 1) 获取并校验目标记录
        Schedule s = scheduleMapper.selectById(id);
        if (s == null) throw new IllegalArgumentException("schedule not found");
        if (req == null) throw new IllegalArgumentException("empty body");

    // 2) 仅合并非空字段，避免误把必填字段置空
        if (req.title != null) s.setTitle(req.title);
        if (req.content != null) s.setContent(req.content);
        LocalDateTime start = null;
        LocalDateTime end = null;
    // 3) 解析并校验起止时间（如果传入）
        if (req.startTime != null && !req.startTime.isEmpty()) {
            start = LocalDateTime.parse(req.startTime, DTF);
            s.setStartTime(start);
        }
        if (req.endTime != null && !req.endTime.isEmpty()) {
            end = LocalDateTime.parse(req.endTime, DTF);
            s.setEndTime(end);
        }
        if (start != null && end != null && end.isBefore(start)) {
            throw new IllegalArgumentException("endTime must be after startTime");
        }
    // 4) 其他可选字段按需覆盖
        if (req.location != null) s.setLocation(req.location);
        if (req.priority != null) s.setPriority(req.priority);
        if (req.teamId != null) s.setTeamId(req.teamId);
        if (req.remindTime != null) {
            if (req.remindTime.isEmpty()) {
                s.setRemindTime(null);
            } else {
                s.setRemindTime(LocalDateTime.parse(req.remindTime, DTF));
            }
        }
    // 5) 只要进行更新，则刷新最后更新时间
    s.setUpdateTime(LocalDateTime.now());
        scheduleMapper.updateById(s);
    // 6) 返回主键ID用于前端定位
        Map<String, Object> resp = new HashMap<>();
        resp.put("id", s.getScheduleId());
        return resp;
    }

    /** 统计某个用户创建的日程数量 */
    @GetMapping("/count")
    public Long getScheduleCount(@RequestParam Integer creatorId) {
        QueryWrapper<Schedule> qw = new QueryWrapper<>();
        qw.eq("creator_id", creatorId);
        return scheduleMapper.selectCount(qw);
    }

    /** 删除日程：同时尝试清理关联的看板卡片 */
    @PostMapping("/{id}/delete")
    public Map<String, Object> delete(@PathVariable Integer id) {
    // 1) 校验记录存在
        Schedule s = scheduleMapper.selectById(id);
        if (s == null) {
            throw new IllegalArgumentException("schedule not found");
        }
        
    // 2) 先尝试删除相关的看板项（若有），异常不影响主删除逻辑
        try {
            kanbanService.removeItemByScheduleId(id);
        } catch (Exception e) {
            // 忽略看板项删除异常，继续删除日程
        }
        
    // 3) 删除日程
        scheduleMapper.deleteById(id);
        
    // 4) 返回删除确认信息
        Map<String, Object> resp = new HashMap<>();
        resp.put("id", id);
        resp.put("message", "删除成功");
        return resp;
    }
}
